<?php

namespace MoChat\App\NewHome\Action;

use Hyperf\DbConnection\Db;
use MoChat\App\WorkDepartment\Contract\WorkDepartmentContract;
use MoChat\Framework\Action\AbstractAction;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use MoChat\App\Common\Middleware\DashboardAuthMiddleware;
use MoChat\App\Sales\Constants\SalesTaskStatusCode;
use MoChat\App\Sales\Contract\SalesClientTaskContract;
use MoChat\App\Sales\Contract\SalesClientTaskEmployeeContract;
use MoChat\App\Sales\Contract\SalesTaskContract;
use MoChat\Framework\Request\ValidateSceneTrait;
use MoChat\Framework\Exception\CommonException;
use MoChat\Framework\Constants\ErrorCode;
use React\Dns\Query\Query;

/**
 * 客户统计
 * @Controller
 */
class Client extends AbstractAction
{
    use ValidateSceneTrait;

    /**
     * @Inject
     * @var WorkDepartmentContract
     */
    protected $workDepartmentService;

    /**
     * @Middlewares({
     *     @Middleware(DashboardAuthMiddleware::class),
     * })
     * @RequestMapping(path="/dashboard/newHome/client", methods="GET")
     */
    public function handle()
    {
        $user = user();
        // 判断用户绑定企业信息
        if (!isset($user['corpIds']) || count($user['corpIds']) !== 1) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '未选择登录企业，不可操作');
        }
        $data = $this->request->all();
        $this->validated($data);
        $data = $this->typeEnum($data);
        $list = Db::table('client as client')
            ->when(!empty($data['clientName']) || is_numeric($data['clientName']), function ($query) use ($data) {
                $query->where('client.enterprise_name', 'like', '%' . $data['clientName'] . '%');
            })
            ->when(!empty($data['name']) || is_numeric($data['name']), function ($query) use ($data) {
                $query->where('b2b_salesman_name', 'like', '%' . $data['name'] . '%');
                $query->orWhere('b2b_manager_name', 'like', '%' . $data['name'] . '%');
            })
            ->where(function ($query) {
                $query->whereNotNull('client.unique_id')
                    ->orWhere('client.unique_id', '<>', '0')
                    ->orWhere('client.unique_id', '<>', '');
            })
            ->where('is_failure',0)
            ->select([
                'client.id',
                'client.unique_id',
                'client.enterprise_name',
                'client.province',
                'client.city',
                'client.district',
                'client.address',
                'client.b2b_user_type',
                'client.b2b_salesman_name',
                'client.b2b_manager_name',
            ])
            ->paginate();
        if (!empty($list->items())) {
            $client = array_column($list->items(), 'id');
            $call = Db::table('call_record')
                ->whereIn('client_id', $client)
                ->when(!empty($data['start_time']) && !empty($data['end_time']), function ($query) use ($data) {
                    $query->where('created_time', '>=', $data['start_time']);
                    $query->where('created_time', '<', $data['end_time']);
                })
                ->select([
                    Db::raw('COUNT(*) as callNumber'),
                    'client_id',
                ])
                ->groupBy([
                    'client_id'
                ])->get()->toArray();
            $call = empty($call) ? [] : array_column($call, null, 'client_id');

            $clock = Db::table('clock_record')
                ->whereIn('client_id', $client)
                ->when(!empty($data['start_time']) && !empty($data['end_time']), function ($query) use ($data) {
                    $query->where('created_at', '>=', $data['start_time']);
                    $query->where('created_at', '<', $data['end_time']);
                })
                ->select([
                    Db::raw('COUNT(*) as clockNumber'),
                    'client_id',
                ])
                ->groupBy([
                    'client_id'
                ])->get()->toArray();
            $clock = empty($clock) ? [] : array_column($clock, null, 'client_id');

            $uniqueIds = array_column($list->items(), 'unique_id');
            $order = Db::connection('b2b')->table('user_order as order')
                ->join('user as user', 'user.id', '=', 'order.USER_ID')
                ->join('order_status as status', function ($join) {
                    $join->on('status.ID', '=', 'order.ID')
                        ->where('status.PAYMENT', '=', 1);
                })
                ->whereIn('user.unique_id', $uniqueIds)
                ->when(!empty($data['start_time']) && !empty($data['end_time']), function ($query) use ($data) {
                    $query->where('order.CREATE_TIME', '>=', $data['start_time']);
                    $query->where('order.CREATE_TIME', '<', $data['end_time']);
                })
                ->groupBy([
                    'user.unique_id'
                ])
                ->select([
                    Db::raw('SUM(my_order.PAID_AMOUNT) as money'),
                    Db::raw('COUNT(my_order.ID) as orderCount'),
                    'user.unique_id'
                ])->get()->toArray();
            $order = empty($order) ? [] : array_column($order, null, 'unique_id');
            $district = Db::table('district')
                ->pluck('name', 'id');
            foreach ($list->items() as &$item) {
                $item->callNumber = $call[$item->id]->callNumber ?? 0;
                $item->clockNumber = $clock[$item->id]->clockNumber ?? 0;
                $item->money = $order[$item->unique_id]->money ?? 0;
                $item->orderCount = $order[$item->unique_id]->orderCount ?? 0;
                if ($item->b2b_user_type == 1) {
                    $item->b2b_user_type = '药店';
                }
                if ($item->b2b_user_type == 2) {
                    $item->b2b_user_type = '诊所';
                }
                if ($item->b2b_user_type == 3) {
                    $item->b2b_user_type = '连锁';
                }
                if ($item->b2b_user_type == 4) {
                    $item->b2b_user_type = '商业公司';
                }
                $address = '';
                if (isset($district[$item->province])) {
                    $address = $district[$item->province];
                }
                if (isset($district[$item->city])) {
                    $address .= $district[$item->city];
                }
                if (isset($district[$item->district])) {
                    $address .= $district[$item->district];
                }
                $address .= $item->address;
                $item->address = $address;
            }
            unset($item);
        }
        return $list;
    }

    /**
     * 总客户数
     * @param $startTime
     * @param $endTime
     * @return int
     */
    private function client($startTime, $endTime): int
    {
        return Db::table('client')
            ->where('created_at', '>=', $startTime)
            ->where('created_at', '<', $endTime)
            ->count();
    }

    /**
     * 呼出电话
     * @param $startTime
     * @param $endTime
     * @return int
     */
    private function call($startTime, $endTime): int
    {
        return Db::table('call_record')
            ->where('created_time', '>=', $startTime)
            ->where('created_time', '<', $endTime)
            ->where('call_type', '=', 'out')
            ->count();
    }

    /**
     * 计算
     * @param $now
     * @param $before
     * @return array
     */
    private function compute($now, $before): array
    {
        //现在大于之前
        if ($now > $before) {
            $diff = bcsub((string)$now, (string)$before, 2);
            $rate = $before ? bcdiv($diff, $before, 2) : 1;
            return [
                'count' => $now,
                'type' => 1,
                'rate' => bcmul($rate, 100, 2) . '%'
            ];
        }

        //现在小于或者等于之前
        $diff = bcsub((string)$before, (string)$now, 2);
        $rate = $before ? bcdiv($diff, $before, 2) : 1;
        return [
            'count' => $now,
            'type' => 2,
            'rate' => bcmul($rate, 100, 2) . '%'
        ];
    }

    /**
     * 时间处理
     * @param $data
     * @return array
     */
    private function typeEnum($data): array
    {
        $timeRange = [];
        //今日
        if ($data['type'] == 1) {
            $timeRange = [
                'start_time' => date('Y-m-d 00:00:00'),
                'end_time' => date('Y-m-d H:i:s'),
            ];
        }
        //昨日
        if ($data['type'] == 2) {
            $timeRange = [
                'start_time' => date('Y-m-d 00:00:00', strtotime('-1 day')),
                'end_time' => date('Y-m-d 00:00:00'),
            ];
        }
        //本月
        if ($data['type'] == 3) {
            $timeRange = [
                'start_time' => date('Y-m-01 00:00:00'),
                'end_time' => date('Y-m-d H:i:s'),
            ];
        }
        //上月
        if ($data['type'] == 4) {
            $start = date('Y-m-01 00:00:00', strtotime('-1 month'));
            $timeRange = [
                'start_time' => date('Y-m-01 00:00:00', strtotime('-1 month')),
                'end_time' => date('Y-m-d H:i:s', strtotime('+1 month', strtotime($start))),
            ];
        }
        //默认
        return array_merge($data, $timeRange);
    }


    /**
     * 验证规则.
     */
    protected function rules(): array
    {
        return [
            'type' => 'in:1,2,3,4',
        ];
    }

    /**
     * 获取已定义验证规则的错误消息.
     */
    protected function messages(): array
    {
        return [
            'type.in' => 'type参数错误',
        ];
    }
}
